"""
数据交换处理
"""
import copy
import json
import re

import allure
import jsonpath

from commons.files import YamlFile
from commons.models import CaseInfo
from commons.templates import Template
import logging

logger = logging.getLogger(__name__)


class Exchange:

    def __init__(self, path):
        self.file = YamlFile(path)

    @allure.step('提取变量')
    def extract(self, resp, var_name, attr, expr: str, index: int):
        """
        数据提取并保存
        :param resp: 响应数据
        :param var_name: 变量名
        :param attr: 属性(从resp响应json/text中)
        :param expr: 表达式（jsonpath、xpath、正则）
        :param index: 位置序号
        :return:
        """
        # resp中json是方法不是属性，需要改为属性
        resp = copy.deepcopy(resp)  # 避免数据被破坏深拷贝
        try:
            resp.json = resp.json()
        except json.decoder.JSONDecodeError:
            resp.json = {'msg': '非json格式数据'}

        data = getattr(resp, attr)  # 找到数据源，反射从resp响应json/text中找到cookies
        if expr.startswith('/'):
            # 是xpath
            ...
        elif expr.startswith('$'):
            # 是jsonpath
            data = dict(data)  # 强转字典
            res = jsonpath.jsonpath(data, expr)
        else:
            # 是正则
            res = re.findall(expr, str(data))
        print(f'{res=}')
        if res:  # 若有数据（列表）
            value = res[index]
        else:
            value = '没有提取到数据'

        logger.debug(f'{var_name} = {value}')
        self.file[var_name] = value  # 保存变量值
        self.file.save()  # 持久化存储到文件中

    @allure.step('替换变量')
    def replace(self, case_info: CaseInfo):
        """
        提取后的数据替换
        :param case_info:
        :return:
        """
        # 1、将case_inf转成字符串
        case_info_str = case_info.to_yaml()
        # 2、替换字符串
        # case_info_str = Template(case_info_str).safe_substitute(self.file)
        case_info_str = Template(case_info_str).render(self.file)
        # 3、将字符串转成case_info
        new_case_info = case_info.by_yaml(case_info_str)

        return new_case_info


if __name__ == '__main__':
    # 单元测试
    class MockResponse:
        text = '{"name": "msjy", "age": 20, "data": [1, 6, 8]}'

        def json(self):
            return json.loads(self.text)


    mock_resp = MockResponse()
    print(mock_resp.text)
    print(mock_resp.json())

    exchange = Exchange(r'D:\PycharmProjects\api_framework\exchange.yaml')
    # exchange.extract(mock_resp, "name", "text", '"name": "(\w+)"', 0)
    # exchange.extract(mock_resp, "age", "text", '"age": (\d+)', 0)
    # exchange.extract(mock_resp, "data", "text", '"data": \[(.*)\]', 0)

    exchange.extract(mock_resp, "name", "json", '$.name', 0)
    exchange.extract(mock_resp, "age", "json", '$.age', 0)
    exchange.extract(mock_resp, "data", "json", '$.data[2]', 0)
